using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Acme.BookStore.EntityFrameworkCore;
using Acme.BookStore.Hubs;
using Acme.BookStore.StockManagement;
using Acme.BookStore.StockManagement.Dtos.KucunZhuXinxi;
using Acme.BookStore.StockManagement.Services;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Volo.Abp.Domain.Repositories;

namespace Acme.BookStore.Services
{
    /// <summary>
    /// 库存大屏数据后台服务
    /// </summary>
    public class StockDashboardService : BackgroundService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IHubContext<DashboardHub> _hubContext;
        private readonly ILogger<StockDashboardService> _logger;
        private Timer _timer = null!;

        /// <summary>
        /// 构造函数
        /// </summary>
        public StockDashboardService(
            IServiceProvider serviceProvider,
            IHubContext<DashboardHub> hubContext,
            ILogger<StockDashboardService> logger)
        {
            _serviceProvider = serviceProvider;
            _hubContext = hubContext;
            _logger = logger;
        }

        /// <summary>
        /// 执行后台服务
        /// </summary>
        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("库存大屏数据服务已启动");

            StartTimer();

            return Task.CompletedTask;
        }

        private void StartTimer()
        {
            _timer = new Timer(PushDashboardData, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
        }

        /// <summary>
        /// 推送大屏数据
        /// </summary>
        private async void PushDashboardData(object? state)
        {
            try
            {
                var dashboardData = await GetStockDashboardData();
                await _hubContext.Clients.Group("StockDataSubscribers").SendAsync("ReceiveStockMainUpdate", dashboardData);
                _logger.LogDebug("已向订阅客户端推送最新库存数据");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "推送库存大屏数据时发生错误");
            }
        }

        /// <summary>
        /// 获取库存大屏数据
        /// </summary>
        private async Task<object> GetStockDashboardData()
        {
            try
            {
                // 创建新的作用域
                using var scope = _serviceProvider.CreateScope();
                
                // 直接获取DbContext
                using var dbContext = scope.ServiceProvider.GetRequiredService<BookStoreDbContext>();
                
                // 直接使用DbContext查询数据
                var stocks = await dbContext.KucunZhuXinxis
                    .AsNoTracking() // 不跟踪实体变化，提高性能
                    .ToListAsync();
                
                if (stocks == null || !stocks.Any())
                {
                    return new
                    {
                        TotalStock = 0,
                        TotalAmount = 0,
                        StockByWarehouse = new List<object>(),
                        StockByType = new List<object>(),
                        LowStockItems = new List<object>(),
                        UpdateTime = DateTime.Now
                    };
                }

                // 计算统计数据
                var totalStock = stocks.Sum(s => s.CurrentStock);
                var totalAmount = stocks.Sum(s => s.StockAmount);
                
                var stockByWarehouse = stocks
                    .GroupBy(s => s.WarehouseName)
                    .Select(g => new
                    {
                        WarehouseName = g.Key ?? "未知仓库",
                        StockCount = g.Sum(s => s.CurrentStock),
                        StockAmount = g.Sum(s => s.StockAmount)
                    })
                    .OrderByDescending(g => g.StockCount)
                    .ToList();
                    
                // 按货品类型统计
                var stockByType = stocks
                    .GroupBy(s => s.GoodsType)
                    .Select(g => new
                    {
                        GoodsType = g.Key ?? "未知类型",
                        StockCount = g.Sum(s => s.CurrentStock),
                        StockAmount = g.Sum(s => s.StockAmount)
                    })
                    .OrderByDescending(g => g.StockCount)
                    .ToList();
                    
                // 库存预警信息（库存小于10的物品）
                var lowStockItems = stocks
                    .Where(s => s.CurrentStock < 10)
                    .OrderBy(s => s.CurrentStock)
                    .Take(10)
                    .Select(s => new
                    {
                        s.GoodsCode,
                        s.GoodsName,
                        s.CurrentStock,
                        s.WarehouseName,
                        s.Specification,
                        s.Unit
                    })
                    .ToList();

                // 构建返回的数据对象
                var dashboardData = new
                {
                    TotalStock = totalStock,
                    TotalAmount = totalAmount,
                    StockByWarehouse = stockByWarehouse,
                    StockByType = stockByType,
                    LowStockItems = lowStockItems,
                    UpdateTime = DateTime.Now
                };

                return dashboardData;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取库存大屏数据时发生错误");
                return new { Error = "获取数据失败", Message = ex.Message };
            }
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        public override Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("库存大屏数据服务已停止");
            _timer?.Change(Timeout.Infinite, 0);
            return base.StopAsync(cancellationToken);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public override void Dispose()
        {
            _timer?.Dispose();
            base.Dispose();
        }
    }
} 